home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 014 / shell / sub.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  10KB  |  473 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * Matthew Dillon, 24 Feb 1986
  6.  *
  7.  */
  8.  
  9.  
  10. #include <exec/types.h>
  11. #include <exec/exec.h>
  12. #include <libraries/dos.h>
  13. #include <libraries/dosextens.h>
  14. #include "shell.h"
  15.  
  16. #define HM_STR 0
  17. #define HM_REL 1
  18. #define HM_ABS 2
  19.  
  20. extern struct FileLock *Lock(), *DupLock(), *CurrentDir();
  21. extern struct FileLock *Clock;
  22.  
  23. char *
  24. next_word(str)
  25. register char *str;
  26. {
  27.    while (*str  &&  *str != ' '  &&  *str != 9)
  28.       ++str;
  29.    while (*str  && (*str == ' ' || *str == 9))
  30.       ++str;
  31.    return (str);
  32. }
  33.  
  34.  
  35. char *
  36. compile_av(av, start, end)
  37. char **av;
  38. {
  39.    char *cstr;
  40.    int i, len;
  41.  
  42.    len = 0;
  43.    for (i = start; i < end; ++i)
  44.       len += strlen(av[i]) + 1;
  45.    cstr = malloc(len + 1);
  46.    *cstr = '\0';
  47.    for (i = start; i < end; ++i) {
  48.       strcat (cstr, av[i]);
  49.       strcat (cstr, " ");
  50.    }
  51.    return (cstr);
  52. }
  53.  
  54.  
  55.  
  56. Free(ptr)
  57. char *ptr;
  58. {
  59.    static char *old_ptr;
  60.  
  61.    if (old_ptr)
  62.       free (old_ptr);
  63.    old_ptr = ptr;
  64. }
  65.  
  66. /*
  67.  * Add new string to history (H_head, H_tail, H_len,
  68.  *  S_histlen
  69.  */
  70.  
  71. add_history(str)
  72. char *str;
  73. {
  74.    register struct HIST *hist;
  75.  
  76.    while (H_len > S_histlen)
  77.       del_history();
  78.    hist = (struct HIST *)malloc (sizeof(struct HIST));
  79.    if (H_head == NULL) {
  80.       H_head = H_tail = hist;
  81.       hist->next = NULL;
  82.    } else {
  83.       hist->next = H_head;
  84.       H_head->prev = hist;
  85.       H_head = hist;
  86.    }
  87.    hist->prev = NULL;
  88.    hist->line = malloc (strlen(str) + 1);
  89.    strcpy (hist->line, str);
  90.    ++H_len;
  91. }
  92.  
  93. del_history()
  94. {
  95.    if (H_tail) {
  96.       --H_len;
  97.       ++H_tail_base;
  98.       free (H_tail->line);
  99.       if (H_tail->prev) {
  100.          H_tail = H_tail->prev;
  101.          free (H_tail->next);
  102.          H_tail->next = NULL;
  103.       } else {
  104.          free (H_tail);
  105.          H_tail = H_head = NULL;
  106.       }
  107.    }
  108. }
  109.  
  110. char *
  111. get_history(ptr)
  112. char *ptr;
  113. {
  114.    register struct HIST *hist;
  115.    register int len;
  116.    int mode = HM_REL;
  117.    int num  = 1;
  118.    char *str;
  119.  
  120.    if (ptr[1] >= '0' && ptr[1] <= '9') {
  121.       mode = HM_ABS;
  122.       num  = atoi(&ptr[1]);
  123.       goto skip;
  124.    }
  125.    switch (ptr[1]) {
  126.    case '!':
  127.       break;
  128.    case '-':
  129.       num += atoi(&ptr[2]);
  130.       break;
  131.    default:
  132.       mode = HM_STR;
  133.       str  = ptr + 1;
  134.       break;
  135.    }
  136. skip:
  137.    switch (mode) {
  138.    case HM_STR:
  139.       len = strlen(str);
  140.       for (hist = H_head; hist; hist = hist->next) {
  141.          if (strncmp(hist->line, str, len) == 0)
  142.             return (hist->line);
  143.       }
  144.       return (NULL);
  145.    case HM_REL:
  146.       for (hist = H_head; hist && num--; hist = hist->next);
  147.       return ((hist) ? hist->line : NULL);
  148.    case HM_ABS:
  149.       len = H_tail_base;
  150.       for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  151.       return ((hist) ? hist->line : NULL);
  152.    }
  153.    return (NULL);
  154. }
  155.  
  156. replace_head(str1, str2, flag)
  157. char *str1, *str2;
  158. {
  159.    char *str3;
  160.  
  161.    if (str1 == NULL)
  162.       str1 = "";
  163.    if (str2 == NULL) {
  164.       str2 = "";
  165.       flag = 0;
  166.    }
  167.    str3 = ((flag & (FL_EOC|FL_EOL)) == FL_EOC) ? ";" : " ";
  168.    if (H_head) {
  169.       free (H_head->line);
  170.       H_head->line = malloc (strlen(str1)+strlen(str2)+2);
  171.       strcpy (H_head->line, str1);
  172.       strcat (H_head->line, str3);
  173.       strcat (H_head->line, str2);
  174.    }
  175. }
  176.  
  177. perror(str)
  178. char *str;
  179. {
  180.    struct PERROR *per = Perror;
  181.    int err = IoErr();
  182.  
  183.    if (err) {
  184.       for (; per->errstr; ++per) {
  185.          if (per->errnum == err) {
  186.             printf ("%s%s%s\n",
  187.                   per->errstr,
  188.                   (str) ? ": " : "",
  189.                   (str) ? str : "");
  190.             return (err);
  191.          }
  192.       }
  193.       printf ("Unknown DOS error %d %s\n", err, (str) ? str : "");
  194.    }
  195.    return (err);
  196. }
  197.  
  198. /*
  199.  * Disk directory routines
  200.  *
  201.  * dptr = dopen(name, stat)
  202.  *    struct DPTR *dptr;
  203.  *    char *name;
  204.  *    int *stat;
  205.  *
  206.  * dnext(dptr, name, stat)
  207.  *    struct DPTR *dptr;
  208.  *    char **name;
  209.  *    int  *stat;
  210.  *
  211.  * dclose(dptr)                  -may be called with NULL without harm
  212.  *
  213.  * dopen() returns a struct DPTR, or NULL if the given file does not
  214.  * exist.  stat will be set to 1 if the file is a directory.  If the
  215.  * name is "", then the current directory is openned.
  216.  *
  217.  * dnext() returns 1 until there are no more entries.  The **name and
  218.  * *stat are set.  *stat = 1 if the file is a directory.
  219.  *
  220.  * dclose() closes a directory channel.
  221.  *
  222.  */
  223.  
  224. struct DPTR *
  225. dopen(name, stat)
  226. char *name;
  227. int *stat;
  228. {
  229.    struct DPTR *dp;
  230.    int namelen, endslash = 0;
  231.  
  232.    namelen = strlen(name);
  233.    if (namelen && name[namelen - 1] == '/') {
  234.       name[namelen - 1] = '\0';
  235.       endslash = 1;
  236.    }
  237.    *stat = 0;
  238.    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  239.    if (*name == '\0')
  240.       dp->lock = DupLock (Clock);
  241.    else
  242.       dp->lock = Lock (name, ACCESS_READ);
  243.    if (endslash)
  244.       name[namelen - 1] = '/';
  245.    if (dp->lock == NULL) {
  246.       free (dp);
  247.       return (NULL);
  248.    }
  249.    dp->fib = (struct FileInfoBlock *)
  250.          AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  251.    if (!Examine (dp->lock, dp->fib)) {
  252.       perror (name);
  253.       dclose (dp);
  254.       return (NULL);
  255.    }
  256.    if (dp->fib->fib_DirEntryType >= 0)
  257.       *stat = 1;
  258.    return (dp);
  259. }
  260.  
  261. dnext(dp, pname, stat)
  262. struct DPTR *dp;
  263. char **pname;
  264. int *stat;
  265. {
  266.    if (dp == NULL)
  267.       return (0);
  268.    if (ExNext (dp->lock, dp->fib)) {
  269.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  270.       *pname = dp->fib->fib_FileName;
  271.       return (1);
  272.    }
  273.    return (0);
  274. }
  275.  
  276.  
  277. dclose(dp)
  278. struct DPTR *dp;
  279. {
  280.    if (dp == NULL)
  281.       return (1);
  282.    if (dp->fib)
  283.       FreeMem (dp->fib, sizeof(*dp->fib));
  284.    if (dp->lock)
  285.       UnLock (dp->lock);
  286.    free (dp);
  287.    return (1);
  288. }
  289.  
  290. free_expand(av)
  291. char **av;
  292. {
  293.    char **base = av;
  294.  
  295.    if (av) {
  296.       while (*av) {
  297.          free (*av);
  298.          ++av;
  299.       }
  300.       free (base);
  301.    }
  302. }
  303.  
  304. /*
  305.  * EXPAND(wild_name, pac)
  306.  *    wild_name      - char * (example: "df0:*.c")
  307.  *    pac            - int  *  will be set to # of arguments.
  308.  *
  309.  * Standalone, except in requires Clock to point to the Current-Directory
  310.  * lock.
  311.  */
  312.  
  313.  
  314. char **
  315. expand(base, pac)
  316. char *base;
  317. int *pac;
  318. {
  319.    char **eav = (char **)malloc (sizeof(char *));
  320.    int  eleft, eac;
  321.  
  322.    char *ptr, *name;
  323.    char *bname, *ename, *tail;
  324.    int stat, scr;
  325.    struct DPTR *dp;
  326.  
  327.    *pac = eleft = eac = 0;
  328.  
  329.    base = strcpy(malloc(strlen(base)+1), base);
  330.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  331.    for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  332.    if (ptr < base) {
  333.       bname = strcpy (malloc(1), "");
  334.    } else {
  335.       scr = ptr[1];
  336.       ptr[1] = '\0';
  337.       bname = strcpy (malloc(strlen(base)+1), base);
  338.       ptr[1] = scr;
  339.    }
  340.    ename = ptr + 1;
  341.    for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
  342.    scr = *ptr;
  343.    *ptr = '\0';
  344.    tail = (scr) ? ptr + 1 : NULL;
  345.  
  346.    if ((dp = dopen (bname, NULL, &stat)) == NULL  ||  stat == 0) {
  347.       free (bname);
  348.       free (base);
  349.       free (eav);
  350.       puts ("Could not open directory");
  351.       return (NULL);
  352.    }
  353.    while (dnext (dp, &name, &stat)) {
  354.       if (compare_ok(ename, name)) {
  355.          if (tail) {
  356.             int alt_ac;
  357.             char *search, **alt_av, **scrav;
  358.             struct FileLock *lock;
  359.  
  360.             if (!stat)           /* expect more dirs, but this not a dir */
  361.                continue;
  362.             lock = CurrentDir (Clock = dp->lock);
  363.             search = malloc(strlen(name)+strlen(tail)+2);
  364.             strcpy (search, name);
  365.             strcat (search, "/");
  366.             strcat (search, tail);
  367.             scrav = alt_av = expand (search, &alt_ac);
  368.             CurrentDir (Clock = lock);
  369.             if (scrav) {
  370.                while (*scrav) {
  371.                   if (eleft < 2) {
  372.                      char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  373.                      movmem (eav, scrav, sizeof(char *) * (eac + 1));
  374.                      free (eav);
  375.                      eav = scrav;
  376.                      eleft = 10;
  377.                   }
  378.                   eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
  379.                   strcpy(eav[eac], bname);
  380.                   strcat(eav[eac], *scrav);
  381.                   free (*scrav);
  382.                   ++scrav;
  383.                   --eleft, ++eac;
  384.                }
  385.                free (alt_av);
  386.             }
  387.          } else {
  388.             if (eleft < 2) {
  389.                char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  390.                movmem (eav, scrav, sizeof(char *) * (eac + 1));
  391.                free (eav);
  392.                eav = scrav;
  393.                eleft = 10;
  394.             }
  395.             eav[eac] = malloc (strlen(bname)+strlen(name)+1);
  396.             eav[eac] = strcpy(eav[eac], bname);
  397.             strcat(eav[eac], name);
  398.             --eleft, ++eac;
  399.          }
  400.       }
  401.    }
  402.    dclose (dp);
  403.    *pac = eac;
  404.    eav[eac] = NULL;
  405.    free (bname);
  406.    free (base);
  407.    if (eac)
  408.       return (eav);
  409.    free (eav);
  410.    return (NULL);
  411. }
  412.  
  413. /*
  414.  * Compare a wild card name with a normal name
  415.  */
  416.  
  417. #define MAXB   8
  418.  
  419. compare_ok(wild, name)
  420. char *wild, *name;
  421. {
  422.    char *w = wild;
  423.    char *n = name;
  424.    char *back[MAXB][2];
  425.    int  bi = 0;
  426.  
  427.    while (*n || *w) {
  428.       switch (*w) {
  429.       case '*':
  430.          if (bi == MAXB) {
  431.             puts ("Too many levels of '*'");
  432.             return (0);
  433.          }
  434.          back[bi][0] = w;
  435.          back[bi][1] = n;
  436.          ++bi;
  437.          ++w;
  438.          continue;
  439. goback:
  440.          --bi;
  441.          while (bi >= 0 && *back[bi][1] == '\0')
  442.             --bi;
  443.          if (bi < 0)
  444.             return (0);
  445.          w = back[bi][0] + 1;
  446.          n = ++back[bi][1];
  447.          ++bi;
  448.          continue;
  449.       case '?':
  450.          if (!*n) {
  451.             if (bi)
  452.                goto goback;
  453.             return (0);
  454.          }
  455.          break;
  456.       default:
  457.          if (*n != *w) {
  458.             if (bi)
  459.                goto goback;
  460.             return (0);
  461.          }
  462.          break;
  463.       }
  464.       if (*n)  ++n;
  465.       if (*w)  ++w;
  466.    }
  467.    return (1);
  468. }
  469.  
  470.  
  471.  
  472.  
  473.